<template>
  <div class="component-upload-image">
    <el-upload
      action=""
      list-type="picture-card"
      :http-request="uploadImageRequest"
      :before-upload="beforeImageUpload"
      :on-exceed="handleExceed"
      ref="imageUpload"
      :show-file-list="true"
      :file-list="fileList"
      :on-preview="handlePictureCardPreview"
      :before-remove="handleDelete"
      :class="{ hide: fileList.length >= 1 }"
    >
      <i class="el-icon-plus avatar-uploader-icon"></i>
    </el-upload>

    <!-- 上传提示 -->
    <div class="el-upload__tip" v-if="showTip">
      请上传
      <template v-if="fileSize">
        大小不超过 <b style="color: #f56c6c">{{ fileSize }} MB</b>
      </template>
      <template v-if="fileType && fileType.length">
        格式为 <b style="color: #f56c6c">{{ fileType.join('/') }}</b>
      </template>
      的文件
    </div>

    <!-- 预览弹窗 -->
    <el-dialog :visible.sync="dialogVisible" title="预览" width="800px" append-to-body>
      <img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" />
    </el-dialog>
  </div>
</template>

<script>
import { uploadImage } from '@/api/upload';

export default {
  name: 'ImageUpload',
  props: {
    value: {
      type: [String],
      default: ''
    },
    // 图片大小限制（单位：MB）
    fileSize: {
      type: Number,
      default: 1
    },
    // 图片类型限制
    fileType: {
      type: Array,
      default: () => ['jpg', 'png', 'jpeg']
    },
    // 是否显示提示
    showTip: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      dialogImageUrl: '',
      dialogVisible: false,
      fileList: [],
      ossBaseUrl: 'https://jinghaiyang.oss-cn-beijing.aliyuncs.com/app/upload/'
    };
  },
  computed: {
    showTipComputed() {
      return this.showTip && (this.fileType || this.fileSize);
    }
  },
  watch: {
    value: {
      handler(val) {
        if (val) {
          const url = val.startsWith('http') ? val : this.ossBaseUrl + val;
          this.fileList = [
            {
              name: val,
              url: url
            }
          ];
        } else {
          this.fileList = [];
        }
      },
      immediate: true
    },
    fileList: {
      handler(newVal) {
        const url = newVal.length > 0 ? newVal[0].url : '';
        this.$emit('input', url);
      },
      deep: true
    }
  },
  methods: {
    uploadImageRequest(options) {
      const formData = new FormData();
      formData.append('file', options.file);

      uploadImage(formData)
        .then(response => {
            const url = response.data.startsWith('http')
              ? response.data
              : this.ossBaseUrl + response.data;

            this.fileList = [
              {
                name: response.fileName,
                url: url
              }
            ];

            this.$emit('input', url);
        })
    },

    // 上传前校验
    beforeImageUpload(file) {
      let isValidType = false;

      if (this.fileType.length > 0) {
        const fileName = file.name.toLowerCase();
        const ext = fileName.slice(fileName.lastIndexOf('.') + 1);

        isValidType = this.fileType.some(type =>
          fileName.endsWith(`.${type}`) || file.type.includes(type)
        );

        if (!isValidType) {
          this.$message.error(`只能上传 ${this.fileType.join('/')} 格式的图片`);
          return false;
        }
      }

      const isValidSize = file.size / 1024 / 1024 < this.fileSize;
      if (!isValidSize) {
        this.$message.error(`图片大小不能超过 ${this.fileSize} MB`);
        return false;
      }

      return true;
    },

    // 文件超出限制
    handleExceed() {
      this.$message.warning('只能上传一张图片');
    },

    // 删除图片
    handleDelete(file, fileList) {
      this.fileList = [];
      this.$emit('input', '');
      return true;
    },

    // 预览图片
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    }
  }
};
</script>

<style scoped>
.component-upload-image .hide .el-upload--picture-card {
  display: none;
}

.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 100%;
  height: 100%;
  line-height: 158px;
  text-align: center;
}

::v-deep .el-upload-list__item {
  transition: none !important;
}
</style>
